

	/* styleListHdl is a handle to document's style list */
	styleCount = (*styleListHdl)->count;
		
	/* allocate temp buffer to hold list of font IDs used */
	if (!(fontBufHdl = NewHandle (sizeof (short) * styleCount))))
	{
		err = kNotEnufMem;	/* can't allocate */
		goto doneErr;
	}
	
	localFontCount = 0;
	fontBuf = *fontBufHdl;	
	/* dereference handle for efficiency */
	/* 
		NOTE that nothing in this next loop compacts the heap so this pointer will be valid without locking the handle 
	*/

	/* loop through style list, making one entry in fontBuf for each unique font ID in the list */
	for (styleIndex = 0; styleIndex < styleCount; styleIndex++)
	{
		/* get next style list element font number */
		fontID = (*styleListHdl)->style [styleIndex].font;

/* loop through fontBuf to see if we already have font */ 
		font = 0;
		while (font < localFontCount)
		{
			if (fontBuf [font] == fontID)	 /*found it, not unique*/
				break;

			font++;
		}
		
		if (font == localFontCount)	
			/* this case if unique, add it */
			fontBuf [localFontCount++] = fontID; 
	}
	
	/* write the FontList.count (localFontCount) */
	if (err = writeDataSize (localFontCount, fileRef))
		goto doneErr;
	
	/* write FontList.fontMap (FontMap array) to disk */
	for (fontIndex = 0; fontIndex < localFontCount; fontIndex++)		{	
		fontID = fontBuf [fontIndex];
		getLocalFontName (fontID, fontName);
		
		/* write font number */
		nWrite = sizeof (fontID);
		if (err = FSWrite (fileRef, &nWrite, &fontID))
			goto doneErr;

		/* write font name */
		nWrite = fontName [0] + 1;		
		if (err = FSWrite (fileRef, &nWrite , fontName))
			goto doneErr;
	}

	DisposHandle (fontBufHdl);	/* free temporary buffer */



	readSize = nRead = (Size) sizeof (short);		/* read font count */
	if (err = FSRead (fileRef, &nRead, &fontCount))
		goto doneErr;
	
	if (nRead != readSize)
	{
		err = kBadFileFormat;
		goto doneErr;
	}
				
	if (!(ghostFontTbl = NewHandle ((Size)(sizeof (FontList) + 
		(sizeof (FontMap) * (fontCount-1))))))
	{
		err = kNotEnufMem;
		goto doneErr;
	}

	if (!(fontMapHdl = NewHandle ((sizeof (short) * (fontCount << 1)))))
	{
		DisposHandle (ghostFontTbl);
		err = kNotEnufMem;
		goto doneErr;
	}
	
	MoveHHi (ghostFontTbl);
	HLock (ghostFontTbl);

	fontMapIndex = 0;

	(*ghostFontTbl)->count = 0;
	ghostFontPtr = (*ghostFontTbl)->fontMap;
	
	for (index = 0; index < fontCount; index++)
	{
		/* read font number */
		readSize = nRead = (Size) sizeof (short);	
		if (err = FSRead (fileRef, &nRead, &localFont))
			goto doneErr;
		if (nRead != readSize)
		{
			err = kBadFileFormat;
			goto doneErr;
		}

		/* read string length */
		readSize = nRead = 1;
		err = FSRead (fileRef, &nRead, localFontStr);
		/* error check */
	
		/* read font name string */
		readSize = nRead = localFontStr[0];
		err = FSRead (fileRef, &nRead, &localFontStr[1]);
		/* more error checking */


		/* get the system's idea of a font number for this font */
		GetFNum (localFontStr, &systemFont);

		if (systemFont)	/* the font exists */
		{
			if (systemFont != localFont) 	/* agree with ours ? */
			{
				/* case 3: font number conflicts */
				/* store localFont, system font in this map */
				*(*fontMapHdl + fontMapIndex++) = localFont;
				*(*fontMapHdl + fontMapIndex++) = systemFont;
			}
			else	
			{
				/* case 1: we agree on the number */
				/* nothing to do here but I wanted you to see where
					this case was detected */
			}
		}
		else	/* font is not resident in this system */
		{
			/* this code is taken from Apple tech note */

			/* get system font name */
			GetFontName (0, systemFontStr);

			/* does it compare with our font name ? */
			if (!EqualString (localFontStr, systemFontStr, false,false))
			{
				/* case 2: this is a Ghost Font */
				pStrCpy (ghostFontPtr->fontName, localFontStr);
				ghostFontPtr->fontNumber = localFont;
		
				(*ghostFontTbl)->count++;
				ghostFontPtr++;
			}
		}
	} /* read font list loop */

	/* make the pass through the style list and change conflicting fonts */
	count = (*styleListHdl)->count;	
	for (styleIndex = 0; styleIndex < count; styleIndex++)
	{
		for (index = 0 ; index < (fontMapIndex >> 1) ; index += 2)
		{
			localFont = *(*fontMapHdl + index);
			systemFont = *(*fontMapHdl + index + 1);
			
			if ((*styleListHdl)->style [styleIndex].font == localFont)
			{
				/* change style list */
				(*styleListHdl)->style [styleIndex].font = systemFont;
				break;
			}
		}
	}
	
	HUnlock (ghostFontTbl);
	disposeHdl (fontMapHdl);	/* no longer need map */

	if ((*ghostFontTbl)->count)
	{
		count = sizeof (FontList) + (sizeof (FontMap) * 					((*ghostFontTbl)->count - 1));
		SetHandleSize (ghostFontTbl, (Size)count);
		if (err = MemErr ())
			goto doneErr;
	}
	else
	{
		DisposHandle (ghostFontTbl);
		ghostFontTbl = 0L;
	}

	theDoc->ghostFontList = ghostFontTbl;



#define kGhostFontChar		'*'	/* asterisk flags these fonts */
#define kGhostFontDelim		'-'/* dashes delimit Ghost Fonts */
/* ---------------------------------------------------------
	buildFontMenu -	create the font menu from the document's ghost list
	© 1989 by Macreations. All Rights Reserved
---------------------------------------------------------- */
MenuHandle
buildFontMenu (theDoc, fontMenuHdl)
	DocPtr			theDoc;
	MenuHandle			fontMenuHdl;
{
	register char		*fontNamePtr, *fontMapNamePtr;
	FontListHdl			fontListHdl;
	FontMapPtr			fontMapPtr;

	register short		count, font, fontCharCount;
	Str255			fontStr, delimitStr;

	if (!fontMenuHdl)		/* first time, init menu */
	{
		delimitStr [0] = 1;			/* create delimiter string */
		delimitStr [1] = kGhostFontDelim;

		AddResMenu (fontMenuHdl, 'FONT');	/* create menu */
		AppendMenu (fontMenuHdl, delimitStr);
		InsertMenu (fontMenuHdl, hierMenu);
	}
	else if (count = CountMItems (fontMenuHdl))	/* strip old Ghost Fonts 	{									from menu */
		/* search menu from the bottom up */
		GetItem (fontMenuHdl, count, fontStr);

		/* search for dashed line delimiter,
			delete all items until found */
		while (fontStr[1] != kGhostFontDelim)
		{
			DelMenuItem (fontMenuHdl, count--);
			GetItem (fontMenuHdl, count, fontStr);
		}
	}
	
	if (theDoc)
	{
		if (fontListHdl = theDoc->ghostFontList)
		{
			if (count = (*fontListHdl)->count)
			{
				/* add the Ghost Fonts to the menu */
				for (font = 0; font < count; font++)
				{
					fontMapPtr = (*fontListHdl)->fontMap + font;

					/* get the font name, setup name buffer ptr */
					fontMapNamePtr = fontMapPtr->fontName;
					fontNamePtr = fontStr;
					
					/* prepend the asterisk to the name */
					fontCharCount = *fontMapNamePtr++;
					*fontNamePtr++ = fontCharCount + 1;
					*fontNamePtr++ = kGhostFontChar;
					
					/* copy into name buffer */
					while (fontCharCount--)
						*fontNamePtr++ = *fontMapNamePtr++;

					InsMenuItem (fontMenuHdl, fontStr, 999);
				}
			}
		}
	}

	return (fontMenuHdl);

} /* buildFontMenu */



/* ----------------------------------------------------------
	fixFontMenu -	check the correct font menu item
	© 1989 by Macreations
-----------------------------------------------------------*/
static void
fixFontMenu (theDoc, theStyle)
	DocPtr			theDoc;
	TextStyle			*theStyle;
{
	register short		i, item, menuItems;
	short				font, count, base;
	Str255			menuStr;
	FontListHdl			ghostFontHdl;
	FontListPtr			ghostFontPtr;
	
	menuItems = CountMItems (fontMenu);

	/* uncheck all real fonts */
	for (i = 1 ; i <= menuItems; i++)
	{
		GetItem (fontMenu, i, menuStr);
		if (menuStr[1] == '-')
		{
			base = i + 1;	/* the first item of the Ghost Fonts */
			break;
		}
		font = getLocalFNum (menuStr);
		CheckItem (fontMenu, i, font == theStyle->tsFont);
	}
	
	/* now do the Ghost Fonts */
	if (theDoc)
	{
		if (ghostFontHdl = theDoc->ghostFontList)
		{
			if (count = (*ghostFontHdl)->count)
			{
				HLock (ghostFontHdl);
				
				ghostFontPtr = (*ghostFontHdl)->fontMap;
				
				for (i = 0; i < count; i++)
				{
					if ((base + i) > menuItems)	/* done */
						break;

					font = ghostFontPtr->localFont;
					CheckItem (fontMenu, (i + base), font == 							theStyle->tsFont);
					ghostFontPtr++;
				}

				HUnlock (ghostFontHdl);
			}
		}
	}
} /* fixFontMenu */
	


/* -------------------------------------------------getLocalFNum -	return a font number corresponding to a font name
	© 1989 by Macreations. All Rights Reserved
------------------------------------------------------- */
short
getLocalFNum (fontName)
	Str255			fontName;
{
	register short		i, count, strLen;
	short				font;

	register char		*menuNamePtr, *docNamePtr;
	FontListHdl			fontListHdl; 
	FontListPtr			fontListPtr;
	FontMapPtr			fontMapPtr;
	
	/* is this a Ghost Font named with the asterisk ? */
	if (fontName[1] == '*')
	{
		/* strip off asterisk */
		fontName[0]--;
		for (i = 1; i <= fontName[0]; i++)
			fontName[i] = fontName[i+1];
	}
	
	if (gTopDocument)
	{
		if (fontListHdl = gTopDocument->ghostFontList)
		{
			fontListPtr = *fontListHdl;
			if (count = fontListPtr->count)
			{
				fontMapPtr = fontListPtr->fontMap;
			
				/* compare all names in the Ghost Font list with the 
					name passed */
				while (count--)
				{
					menuNamePtr = fontName;
					docNamePtr = fontMapPtr->fontName;
					if ((strLen = *docNamePtr++) == *menuNamePtr++)
					{
						while (strLen--)
						{
							if (*docNamePtr++ != *menuNamePtr++)
								break;
						}

						if (strLen < 0)	/* names compare */
							return (fontMapPtr->localFont);
					}
					fontMapPtr++;
				}
			}
		}
	}

	/* if we got here, then its not a Ghost Font, call the system */	
	GetFNum (fontName, &font);
	return (font);
	
} /* getLocalFNum */


/* -------------------------------------------------------	getLocalFontName	-	return the name corresponding to the font
	© 1989 by Macreations. All Rights Reserved
------------------------------------------------------- */
void
getLocalFontName (localFont, fontName)
	short				localFont;
	Str255			fontName;
{
	short				count;
	FontListHdl			fontListHdl; 
	FontListPtr			fontListPtr;
	FontMapPtr			fontMapPtr;
	
	if (gTopDocument)	
	{
		if (fontListHdl = gTopDocument->ghostFontList)
		{
			fontListPtr = *fontListHdl;
			if (count = fontListPtr->count)
			{
				fontMapPtr = fontListPtr->fontMap;
				while (count--)
				{
					if (fontMapPtr->localFont == localFont)
					{
						BlockMove (fontMapPtr->fontName, fontName, 						   (Size)(fontMapPtr->fontName[0] + 1));
						return;
					}
					fontMapPtr++;
				}
			}
		}
	}
	
	GetFontName (localFont, fontName);
	if (!fontName [0])
		pStrCpy (fontName, "\pUnknown Font");
	
} /* getLocalFontName */

